/**
 * Created by Hata Kokoro on 6/28/2017.
 */

var Const = require('./const.js');
var Poker = require('../Poker/Poker');
var PokerRoom = require('../Poker/room').PokerRoom;
var SubCode = require('../subCode');
var util = require("./util")
var rules=require('./rule');
var RoundStatus = {
    'WAITING': 1,   // 等待其它玩家准备
    'PREPARE': 2,   // 准备人数足够，将继续等待，其它玩家依然可以准备
    'READY': 3,     // 就绪，开始游戏
    'PLAY': 4,     // 玩家选牌
}


exports.BNCRoom = PokerRoom.extend({
    /**
     * Room Config
     */
    _roundStatus: RoundStatus.WAITING,
    _iMaxTurn:0,
    _bFlowerCards:false,
    _szDealerRules:null,
    _iMaxPlayer:0,
    _szSpecType:false,
    _robDealerBet:null,
    _arrNormalPlayer:null,
    _selectWaitTime:0,
    init:function(rid,creator,msg){
        this._super(rid,creator,msg);
        var cfg=this.getOptions();
        this._iMaxTurn=cfg.m_iMaxTurn;
        this._bFlowerCards=cfg.m_flowerCards;
        this._szDealerRules=cfg.m_DealerRules;
        this._iMaxPlayer=cfg.m_iMaxPlayer;
        this._szSpecType=cfg.m_szSpecialType;
        this._arrNormalPlayer=[];
        this._roundStatus = RoundStatus.WAITING;


        this.getSubConfig().roomPlayerNum = this._iMaxPlayer
    },
    /******************************************************************
     * Overridden Interface
     ******************************************************************/
    getRoomConfig:function(){
        var cfg = this._super();
        cfg.waitTimeoutTime = 180;
        cfg.waitTimeoutAfter = 10;
        return cfg;
    },

    onBeforeStartNewRound:function(){
        this._super();
        this._selectWaitTime=0;
    },
    onAfterStartNewRound:function() {
        this._super();
        this._startPlay();
        logger.debug("ON AFTER START NEW ROUND");
    },
    onSettlement:function(){
        this._super();
        this._Settlement();
        this._broadcastAllHands();
    },
    onCurRoundFinished:function(){
        this._super();
        this._roundStatus=RoundStatus.WAITING;
       // clearTimeout();
    },
    checkStartNewRound:function() {
        logger.debug("CHECK START NEW ROUND");
        if (this.isPlaying()) {
            return false;
        }
        var subCfg = this.getSubConfig();
        logger.debug(subCfg.roomPlayerMin);
        if (this.getPlayerCount() == this.getReadyPlayerCount() &&
            this.getReadyPlayerCount() >= subCfg.roomPlayerMin) {
            logger.debug("ROUND START is TRUE");
            this._roundStatus = RoundStatus.READY;
            logger.debug("set RoundStatus READY")
            return true;
        } else
            return false;
    },

    getSettlementInfo:function(){
        var info = this._super();
    },
    /******************************************************************
     * Room Interface
     ******************************************************************/
    /**
     * @param player
     * @param msg{i_Point}
     * @param callback
     */
    handleSetBasePoint: function (player,msg,callback) {
        if(this.getDealerIndex()==player.getIndex()) {
            player.setBasePoint(1);
            callback({code:0});
            return;
        }else{
            player.setBasePoint(msg.i_Point); callback({code:0});
            return;
        }
    },
    /**
     * @param player
     * @param msg{i_bet(1/2/3), _robDealer(-1/0/1)}
     * @param callback
     */
    handleRobDealer:function(player,msg,callback) {
        logger.debug("HANDLE ROB DEALER")
        if (this._szDealerRules != "BY_ROB") {
            callback({code: "CURRENT ROOM MODE NOT SUPPORT ROB DEALER"});
            return;
        }
        //this._robDealerBet[msg._uid]=msg.i_bet;
        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING});
            return;
        }

        if (!msg.hasOwnProperty('value') || isNaN(msg.value)) {
            callback({code: Code.ARGS_INVALID});
            return;
        }

        player._ibetRate = msg.value;
        if (msg.value == 0) {
            player._robDealer = -1;
        }
        if (msg.value != 0) {
            player._robDealer = 1;
        }

        this.broadcast("onPlayerRobDealer", {
            "playerUid": player._uid,
            "playerIndex": player.getIndex(),
            "betRate": player._ibetRate
        });
        callback({});
    },
    /**
     * @param player
     * @param msg  {uid,cards}
     * @param callback
     */
    handleSelectCards: function (player,msg,callback) {
        logger.debug(msg);
        if (!msg.cards) {
            callback({code:"AUTO_SELECTED_BY_SERVER"});
        }

        if (!player.isPlaying()) {
            callback({code: Code.PLAYER_NOT_PLAYING}); return;
        }

        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING}); return;
        }

        if (this.isCurRoundFinished()) {
            callback({code: Code.ROOM_ROUND_FINISHED}); return;
        }

        var cards = msg.cards;
        if (!ExObject.isArray(cards)) {
            callback({code: Code.ARGS_VALUE_WRONG}); return;
        }

        if (!player.setSelectedCards(cards)) {
            callback({code: SubCode.CARD_NOT_EXIST}); return;
        }

        callback({});

        this.broadcast("onPlayerSelectCards", {
            playerIndex: player.getIndex(),
            selectNum: msg.cards.length
        });

        var isAllSelected = true;
        this.enumPlaying(function(eIndex, ePlayer) {
            if (!ePlayer.isSelectedCards()) {
                isAllSelected = false;
            }
        });

        if (isAllSelected) {
            logger.debug("GO ON SETTLEMENT")
            this.settlementCurRound(500);
        }
    },
    /******************************************************************
     * Room Interface
     ******************************************************************/
    _setRoomStartHandNum: function (num) {
        this.enumPlayers(function(index,player){
            player._startHandNum=num;
        })
    },

    _startPlay: function () {
        if(this._szDealerRules=="BY_ROB") {
            this._setRoomStartHandNum(5);
            this.initPlayersHandCards();   //init palyer's hand
            this._waitSetBasePoint();         //wait player set base point
            logger.debug("WAIT ROB DEALER ENTERED")
            this._waitRobDealer();             //wait player rob dealer
            this._dispatchHandInfo();       //dispatch each players' hand info
            this._waitSelectCards();          //wait for player select card to compare
        }

        if(this._szDealerRules=="BY_RANDOM"){
            this._setRoomStartHandNum(5);
            this.initPlayersHandCards();
            this._SetDealerByRandom();
            this._waitSetBasePoint();

            this._dispatchHandInfo();
            this._waitSelectCards();
        }

        if(this._szDealerRules=="BY_ROTATE"){
            this._setRoomStartHandNum(5);
            this.initPlayersHandCards();
            this._SetDealerByRotate();
           // this._waitSetBasePoint();

            this._dispatchHandInfo();
            this._waitSelectCards();
        }
    },

    _dispatchHandInfo:function(){
        this.enumPlaying(function (index,player){
           player.sendRoundInfo();
        });
    },

    _waitRobDealer:function() {
        setTimeout(function () {
            if (!this.isPlaying()) {
                return;
            }
            /*
             if (this._roundStatus != RoundStatus.READY) {
             logger.debug(this._roundStatus);
             logger.debug("12222222222222222222222222222222221")
             return;
             }
             */

            this.enumPlaying(function (eIndex, ePlayer) {
                if (ePlayer.getRobDealer() == -1) {
                    ePlayer.setRobDealer(0);
                    this.broadcast("onPlayerRobDealer", {
                        playerIndex: ePlayer.getIndex(),
                        value: 0
                    });
                }
            }.bind(this));
            if (this._szDealerRules == "BY_ROB") {
                this._dealRobDealerAllSet();
            }
        }.bind(this), this.getHideOption("startWaitMS"));
    },

    _dealRobDealerAllSet: function () {
        //var arr0 = [];
        //var arr1 = [];
        var tmp=0;
        this.enumPlaying(function(eIndex, ePlayer) {
           /*
            if (ePlayer.getRobDealer()) {
                arr1.push(eIndex);
            } else {
                arr0.push(eIndex);
            }
            */
            if(ePlayer.getRobDealer()){
                tmp=eIndex;
                var nextPlayer = this.getNextPlaying(eIndex);
                if(nextPlayer._ibetRate>ePlayer._ibetRate){
                    tmp=this.getNextIndex(eIndex);
                }
            }
        }.bind(this));
        this._dealerIndex=tmp;
        //this._dealerIndex = Ext.randArray(arr1) || Ext.randArray(arr0);

        this.broadcastReplay("onDealerChanged", {
            dealer: this._dealerIndex
        });
        if(this._szDealerRules=="BY_ROB") {
            this._waitSelectCards();
        }
    },

    _waitSelectCards: function() {
        this._roundStatus = RoundStatus.PLAY;
        this._selectWaitTime = Date.getStamp();
        setTimeout(function() {

            this.settlementCurRound();

        }.bind(this), this.getHideOption("selectWaitMS"));
    },

    _waitSetBasePoint: function () {
        setTimeout(function() {
            if (!this.isPlaying()) {
                return;
            }

            if (this._roundStatus != RoundStatus.READY) {
                return;
            }

            this.enumPlaying(function(eIndex, ePlayer) {
                if (ePlayer.getBasePoint() == -1) {
                    ePlayer.setBasePoint(1);
                    this.broadcast("onPlayerSetBasePoint", {
                        playerIndex: ePlayer.getIndex(),
                        value: 0
                    });
                }
            }.bind(this));

            //this._dealRobDealerAllSet();

        }.bind(this), this.getHideOption("startWaitMS"));
    },
    /**
     * Set dealer index by random
     * @private
     */
    _SetDealerByRandom:function(){
        this._dealerIndex = ExNumber.randRange(1,this.getPlayerCount());
        logger.debug("dealer Index:"+this._dealerIndex);
        this.broadcastReplay("onDealerChanged", {
            dealer: this._dealerIndex
        });
    },
    /**
     * Set dealer index by rotate
     * @private
     */
    _SetDealerByRotate:function(){
        if(this._curRound>=2){
            this._dealerIndex = this.getNextPlaying(this._dealerIndex);
        }else {
            this._dealerIndex = this.getPlayerIndex(this.getCreator());
            logger.debug("SET DEALER BY ROTATE")
            logger.debug("dealer Index : " + this._dealerIndex);
        }
        this.broadcastReplay("onDealerChanged", {
            dealer: this._dealerIndex
        });
    },

    /**
     * build array for normal player
     * @private
     */
    _BuildNormalPlayerArray:function() {
        var tmp = [];

        console.log ("build two");

        this.enumPlaying(function (index, player) {
            logger.debug("index: "+ index);
            logger.debug("dealerIndex: "+this._dealerIndex);
            if (index != this._dealerIndex) {

                console.log ("add nor player");
                tmp.push(player);
            }
        }.bind(this));
        this._arrNormalPlayer = tmp;
    },
    /**
     * Each player compare cards with Dealer
     * Calculate each players' round Score
     * @private
     */
    _Settlement:function() {
        this._BuildNormalPlayerArray();
        logger.debug("arrNormalPlayer: "+ this._arrNormalPlayer);
        this.enumPlaying(function(index,player){
           if(player._selectedCards==null||player._selectedCards.length==0){
              player._selectedCards= player.getBestCombine();
           }
        });
        var dealer = this.getPlayerByIndex(this._dealerIndex);
        for (var i = 0; i < this._arrNormalPlayer.length; i++) {
            var player = this._arrNormalPlayer[i];
            if (this._CompareWithDealer(this._arrNormalPlayer[i],
                    this.getPlayerByIndex(this._dealerIndex))
            ) {
                logger.debug("--debug: Settlement :")
                var rate = Const.ScoreTable[player._iPowerRating];
                var score= dealer._iBasePoint * rate;
                player.addRoundScore(score);
                dealer.addRoundScore(-score);
                player._stat.roundPattern=player._iPowerRating;
                dealer._stat.roundPattern=dealer._iPowerRating;
                logger.debug("normal win");
                logger.debug("score: "+ score);
                logger.debug("rate: "+rate);
                logger.debug("basePoint: "+dealer._iBasePoint);
                logger.debug("dealer roundScore :"+dealer._stat.roundScore)
                logger.debug("normal roundScore :"+player._stat.roundScore);
            } else {
                logger.debug("--debug: Settlement :")
                var rate = Const.ScoreTable[dealer._iPowerRating];
                var score = player._iBasePoint * rate
                dealer.addRoundScore(score);
                player.addRoundScore(-score)
                logger.debug("dealer win");
                logger.debug("score: "+ score);
                logger.debug("rate: "+rate);
                logger.debug("basePoint: "+player._iBasePoint);
                logger.debug("dealer roundScore :"+dealer._stat.roundScore)
                logger.debug("normal roundScore :"+player._stat.roundScore);
            }
        }
    },
    /**
     * Compare hands between dealer and normal
     * @param normal
     * @param dealer
     * @returns {boolean} true: normal wins  false:dealer wins
     * @private
     */
    _CompareWithDealer:function(normal,dealer) {
        logger.debug("COMPARE WITH DEALER: debug")
        logger.debug(dealer);
        this._showPlayerInfo();
        if (this._szSpecType == true) {
           return this._withSpecialPattern(normal,dealer);
        }
        //this._showPlayerInfo();
        /**
         *
         //Round 1: if Player has Niu
         if (rules.HasNiu(normal._handCards.getCards())) {
            if (rules.HasNiu(dealer._handCards.getCards())==false) {
                return true;
            }
            //Round 2: Compare powerRating of unselected Cards
            var normalPoint = rules.GetSecondPattern(normal._unSelectedCards);
            normal._iPowerRating = normalPoint;
            logger.debug("PLAYER PR: " + normalPoint);
            var dealerPoint = rules.GetSecondPattern(dealer._unSelectedCards);
            dealer._iPowerRating = dealerPoint;
            logger.debug("DEALER PR: " + normalPoint);
            if (normal._iPowerRating > dealer._iPowerRating) {
                logger.debug("NORMAL WINS")
                return true;
            }// normal wins
            else {
                logger.debug("DEALER WINS")
                return false;
            }//dealer wins
        } else if (rules.HasNiu(dealer._unSelectedCards)) {
            return (//true:normal wins false:dealer wins
                rules.CompareSingleCard(dealer._handCards.getCards(), normal._handCards.getCards())
            )
        } else {
            //dealer wins
            return false;
        }
         */
        return this._withoutSpecialPattern(normal, dealer);
    },
    _broadcastAllHands: function () {
        var playerHandTable = {};
        this.enumPlayers(function (index, player) {
            var playerData = new Object();
            if (rules.isNiu(player._selectedCards)) {
                playerData["Pattern"] = rules.GetSecondPattern(player._unSelectedCards);
            } else {
                playerData["Pattern"] = 0;
            }
            playerData["Hands"] = player._handCards.getCards();

            /*playerHandTable[index]={
             "Pattern":rules.GetSecondPattern(player._unSelectedCards),
             "Hands":player._handCards.getCards()
             }*/
            var hands = util.Hands2Array(player._handCards.getCards());
            logger.debug("hands " + hands);
            playerHandTable[index] = playerData;
        })
        this.broadcast("onShowHandCards", playerHandTable);
    },

    _showPlayerInfo: function () {
        logger.debug("--debug: PLAYER'S STATE")
        this.enumPlaying(function(index,player){
            logger.debug("index: "+index);
            logger.debug("selected :"+player._selectedCards);
            logger.debug("unselected :"+player._unSelectedCards);
            logger.debug("Second Pattern :"+rules.GetSecondPattern(player._unSelectedCards))
            logger.debug("-----------------");
        })
    },
    /**
     *Room mode: no Special Pattern
     * @param normal
     * @param dealer
     * @returns {boolean} true: normal wins ||  false: dealer wins
     * @private
     */
    _withoutSpecialPattern:function(normal,dealer){
        var normalPR= 0;
        var dealerPR=0;


        if(rules.isNiu(normal._selectedCards)){
            console.log ("NORMAL HAS NIU");
            normalPR=rules.GetSecondPattern(normal._unSelectedCards);
        }else{
            normalPR=0;
        }

        if(rules.isNiu(dealer._selectedCards)){
            console.log ("dealer HAS NIU");
            dealerPR=rules.GetSecondPattern(dealer._unSelectedCards);
        }else{
            dealerPR=0;
        }
        normal._iPowerRating=normalPR;
        dealer._iPowerRating=dealerPR;

        logger.debug("------DEBUG-------")
        logger.debug("normal PR: "+ normalPR);
        logger.debug("dealer PR: "+ dealerPR);
        logger.debug("------DEBUG-------")

        if(normalPR>dealerPR){
            return true;
        }else if(dealerPR>normalPR){
            return false;
        }else if(dealerPR==normalPR){
            if(normal._getMaxCard()>dealer._getMaxCard()){
                return true;
            }else{
                return false;
            }
            //return rules.CompareSingleCard(dealer._handCards.getCards(), normal._handCards.getCards());
        }
    },
    /**
     * Room mode: has Special Pattern
     * @param [object]normal
     * @param [object]dealer
     * @returns {boolean}
     * @private
     */
    _withSpecialPattern: function (normal,dealer) {
        var playerPattern = rules.SpecialPatternCheck(normal._handCards.getCards());
        var dealerPattern = rules.SpecialPatternCheck(dealer._handCards.getCards());

        if(playerPattern==0){
            if(rules.isNiu(normal._selectedCards)){
                playerPattern= rules.GetSecondPattern(normal._unSelectedCards);
            }
        }

        if(dealerPattern==0){
            if(rules.isNiu(dealer._selectedCards)){
                dealerPattern=rules.GetSecondPattern(dealer._unSelectedCards);
            }
        }

        normal._iPowerRating=playerPattern;
        dealer._iPowerRating=dealerPattern;

        if(playerPattern>dealerPattern){
            return true;
        }else if(dealerPattern>playerPattern){
            return false
        }else if(dealerPattern==playerPattern){
            if(normal._getMaxCard()>dealer._getMaxCard()){
                return true;
            }else{
                return false;
            }
            //return rules.CompareSingleCard(dealer._handCards.getCards(),normal._handCards.getCards());
        }
    }
});

